#include "MessagePack.h"
#include "CommandArgs.h"
#include "CommonFunc.h"
#include "MessageCommand.h"

#include "boost/any.hpp"

#include <stdexcept>

MessagePack::MessagePack(int socketFd)
:m_SocketFd(socketFd)
{

}

void MessagePack::toSocket(const CommandArgs &args) const
{
	int messageType = boost::any_cast<int>( args.getArg("messageType") );

	if(!SendData(m_SocketFd, reinterpret_cast<char*>(&messageType), sizeof(messageType) ) )
	{
		throw std::runtime_error("Send message type error");
	}
	if (messageType == MessageCommand::MouseMessage)
	{
		unsigned flags = boost::any_cast<unsigned>( args.getArg("flags") );
		int pointX = boost::any_cast<int>( args.getArg("pointX") );
		int pointY = boost::any_cast<int>( args.getArg("pointY") );
		if (!SendData(m_SocketFd, reinterpret_cast<char*>(&flags), sizeof(flags)) ||
			!SendData(m_SocketFd, reinterpret_cast<char*>(&pointX), sizeof(pointX)) ||
			!SendData(m_SocketFd, reinterpret_cast<char*>(&pointY), sizeof(pointY)) )
		{
			throw std::runtime_error("Send message arguments error");
		}
	}
	else if (messageType == MessageCommand::KbdMessage)
	{
		Byte virtualK = boost::any_cast<Byte>( args.getArg("virtualK") );
		Byte scanCode = boost::any_cast<Byte>( args.getArg("scanCode") );
		unsigned flags = boost::any_cast<unsigned>( args.getArg("flags") );
		if (!SendData(m_SocketFd, reinterpret_cast<char*>(&virtualK), sizeof(virtualK)) ||
			!SendData(m_SocketFd, reinterpret_cast<char*>(&scanCode), sizeof(scanCode)) ||
			!SendData(m_SocketFd, reinterpret_cast<char*>(&flags), sizeof(flags)) )
		{
			throw std::runtime_error("Send message arguments error");
		}
	}
}

boost::shared_ptr<MessageCommand> MessagePack::createCmdFromSocket() const
{
	int messageType;
	if (!ReceiveData(m_SocketFd, reinterpret_cast<char*>(&messageType), sizeof(messageType), sizeof(messageType) ) )
	{
		throw std::runtime_error("Receive message type error");
	}
	if (messageType == MessageCommand::MouseMessage)
	{
		unsigned flags;
		int pointX;
		int pointY;
		if (!ReceiveData(m_SocketFd, reinterpret_cast<char*>(&flags), sizeof(flags), sizeof(flags)) ||
			!ReceiveData(m_SocketFd, reinterpret_cast<char*>(&pointX), sizeof(pointX), sizeof(pointX)) ||
			!ReceiveData(m_SocketFd, reinterpret_cast<char*>(&pointY), sizeof(pointY), sizeof(pointY)) )
		{
			throw std::runtime_error("Receive message arguments error");
		}

		CommandArgs args;
		args.insertArg("flags", flags);
		args.insertArg("pointX", pointX);
		args.insertArg("pointY", pointY);

		return boost::shared_ptr<MessageCommand>( new MouseCommand(args) );
	}
	else if (messageType == MessageCommand::KbdMessage)
	{
		Byte virtualK;
		Byte scanCode;
		unsigned flags;
		if(!ReceiveData(m_SocketFd, reinterpret_cast<char*>(&virtualK), sizeof(virtualK), sizeof(virtualK)) ||
			!ReceiveData(m_SocketFd, reinterpret_cast<char*>(&scanCode), sizeof(scanCode), sizeof(scanCode)) ||
			!ReceiveData(m_SocketFd, reinterpret_cast<char*>(&flags), sizeof(flags), sizeof(flags)) )
		{
			throw std::runtime_error("Receive message arguments error");
		}

		CommandArgs args;
		args.insertArg("virtualK", virtualK);
		args.insertArg("scanCode", scanCode);
		args.insertArg("flags", flags);

		return boost::shared_ptr<MessageCommand>( new KbdCommand(args) );
	}

	return boost::shared_ptr<MessageCommand>( );
	 
}